//
//  YHGameLayerMain.cpp
//  ThunderWarriors
//
//  Created by mac on 12-12-23.
//
//

#include "YHGameLayerMain.h"
#include "YHGameSceneManager.h"
#include "YHGameMainScene.h"
#include "YHGameDefine.h"

enum  {
    kTagPalyer = 1,
    kTagBatchNode=2,
};
const int offset = 1;

IMPLEMENT_CREATE_CLASS(YHGameLayerMain)

BEGIN_PROPERTY(YHGameLayerMain)
END_PROPERTY()

YHGameLayerMain::YHGameLayerMain(){
    REGISTER_PROPERTY();
    m_gameLayerMap = NULL;
}
YHGameLayerMain::~ YHGameLayerMain(){
    _enemySprites->release();
    _enemySprites=NULL;
    _bulletSprites->release();
    _bulletSprites=NULL;
    RELEASE_DYNAMIC_PROPERTY(YHGameLayerMain);
}

bool YHGameLayerMain::init(){
    bool bRet = false;
    
    
    
    
    
    //init spriteBatchNode
    CCSpriteBatchNode *batchNode = CCSpriteBatchNode::create("gameArts.png");
    batchNode->setPosition(CCPointZero);
    this->addChild(batchNode,kShipZorder,kTagBatchNode);
    
    //1.get screen's size
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    
    //2.add background
    //CCSprite *bgSprite = CCSprite::createWithSpriteFrameName("background_1.jpg");
    //bgSprite->setPosition(ccp(winSize.width/2, winSize.height/2));
    //batchNode->addChild(bgSprite, -100);
    m_gameLayerMap = YHGameLayerMap::create();
    this->addChild(m_gameLayerMap, kMapZorder);
    m_gameLayerMap->beginScroll(40);
    m_gameLayerMap->pauseScroll();
    loadClouds();
    
    
    //3.add player's plane
    CCSprite *playerSprite = CCSprite::createWithSpriteFrameName("hero_1.png");
    playerSprite->setPosition(ccp(winSize.width/2,playerSprite->getContentSize().height/2+20));
    batchNode->addChild(playerSprite, kShipZorder,kTagPalyer);
    
    //4.init enemy sprites array
    _enemySprites = CCArray::createWithCapacity(10);
    _enemySprites->retain();
    
    //5.initialize 10 enemy sprites & add them to _enemySprites array for future useage
    const int NUM_OF_ENEMIES =10;
    for (int i=0; i<NUM_OF_ENEMIES; ++i) {
        CCSprite *enemySprite = CCSprite::createWithSpriteFrameName("enemy1.png");
        enemySprite->setPosition(ccp(0,winSize.height+enemySprite->getContentSize().height+10));
        enemySprite->setVisible(false);
        batchNode->addChild(enemySprite,kEnemyShipZorder);
        _enemySprites->addObject(enemySprite);
    }
    
    
    


  
    //10.init bullets
    _bulletSprites = CCArray::createWithCapacity(10);
    _bulletSprites->retain();
    for (int i=0; i<NUM_OF_ENEMIES; ++i) {
        CCSprite *bulletSprite = CCSprite::createWithSpriteFrameName("bullet1.png");
        bulletSprite->setPosition(ccp(0,-10));
        bulletSprite->setVisible(false);
        this->addChild(bulletSprite,kShipBulleZorder);
        _bulletSprites->addObject(bulletSprite);
    }
   
    
    //12.init player lives & score
    CCLabelTTF *lifeIndicator =CCLabelTTF::create("生命值：","Arial",20);
    lifeIndicator->setAnchorPoint(ccp(0.0, 0.5));
    lifeIndicator->setPosition(ccp(20, winSize.height-20));
    this->addChild(lifeIndicator,20);

    _lifeLabel =CCLabelTTF::create("3","Arial",20);
    _lifeLabel->setPosition(ccpAdd(lifeIndicator->getPosition(), ccp(lifeIndicator->getContentSize().width+10, 0)));
    this->addChild(_lifeLabel,20);
    
    CCLabelTTF * scoreIndicator = CCLabelTTF::create("分数：","Arial",20);
    scoreIndicator->setAnchorPoint(ccp(0.0, 0.5f));
    scoreIndicator->setPosition(ccp(winSize.width-100, winSize.height-20));
    this->addChild(scoreIndicator,20);
    _scoreLabel=CCLabelTTF::create("00","Arial",20);
    _scoreLabel->setPosition(ccpAdd(scoreIndicator->getPosition(),ccp(scoreIndicator->getContentSize().width+10, 0)));
    this->addChild(_scoreLabel,20);
    
    //13.init lives & score variable
    _totalLives=3;
    _totalScore=0;
    
    
    //14.add game end label
    _gameEndLabel = CCLabelTTF::create("","Arial",40);
    _gameEndLabel->setPosition(ccp(winSize.width/2,winSize.height/2));
    _gameEndLabel->setVisible(false);
    this->addChild(_gameEndLabel,20);
    //15.add game start menu & relative game logic
    _isGameStarted=false;

    
    //18.init player fly animation
    CCAnimation *playerFlyAnimation = this->getAnimationByName("hero_",0.08,2);
    _playerFlyAction = CCRepeatForever::create(CCAnimate::create(playerFlyAnimation));
    _playerFlyAction->retain();
    playerSprite->runAction(_playerFlyAction);
    
    //19.init player & enemy 's blow up animation
    _playerBlowupAnimation = this->getAnimationByName("plane_bao_",0.08,5);
    _playerBlowupAnimation->retain();
    _enemyBlowuoAnimation = this->getAnimationByName("plane2_bao_",0.08,5);
    _enemyBlowuoAnimation->retain();
    
    //20.init colliable flags
    _isEnemyColliable = true;
    _isPlayerColliable = true;
        
    bRet = true;
    return bRet;
}

void YHGameLayerMain::onEnter(){
    CCLayer::onEnter();
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    CCMenuItemFont::setFontSize(20);
    CCMenuItemFont::setFontName("Arial");
    CCMenuItemFont * startItem= CCMenuItemFont::create("开始游戏",this,menu_selector(YHGameLayerMain::menuStartCallback));
    startItem->setPosition(ccp(winSize.width/2, winSize.height/2));
    _startGameMenu = CCMenu::create(startItem, NULL);
    _startGameMenu->setPosition (CCPointZero);
    this->addChild(_startGameMenu, 21);

}
void YHGameLayerMain::update(float dt){
    if (!_isGameStarted) {
        return;
    }
    this->collisionDetection(dt);
    this->updateHUD(dt);    
}


CCAnimation * YHGameLayerMain::getAnimationByName(const char * animName,float delay,int num){
    
    CCArray *animFrames = CCArray::createWithCapacity(num);
    for (int i=1; i<=num; i++) {
        CCString * frameName = CCString::createWithFormat("%s%d.png",animName,i);
        CCSpriteFrame * frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(frameName->getCString());
        animFrames->addObject(frame);
    }
    CCAnimation *animation = CCAnimation::createWithSpriteFrames(animFrames,delay);
    return animation;
}
// a selector callback
void YHGameLayerMain::menuStartCallback(CCObject* pSender){
    _isGameStarted=true;
    CCMenuItem *item=(CCMenuItemFont *) pSender;
    item->setVisible(false);
    //6.spawn enemy after schedule random sec
    this->schedule(schedule_selector(YHGameLayerMain::spawnEnemy), arc4random()%3 +1);
    //7.enable accelerometer
    this->setAccelerometerEnabled(true);
    
    //8.game main loop
    this->scheduleUpdate();
    

    
    //8.添加开始连续滚动背景的代码
   // const int MAX_LEVEL_WIDTH =320;
   // const int MAX_LEVEL_HEIGH =480 * 100;
    //CCSprite *hiddenPlayerSprite = [CCSprite spriteWithSpriteFrameName:@"hero_1.png"];
   // hiddenPlayerSprite.position = ccp(winSize.width/2, winSize.height/2);
   // [self addChild:hiddenPlayerSprite z:-4 tag:1024];
    //_totalSeconds = 60;
    //id move = [CCMoveBy actionWithDuration:_totalSeconds position:ccp(0, MAX_LEVEL_HEIGH)];
    //[hiddenPlayerSprite runAction:move];
    //让背景开始滚动
   // [_backgroundNode runAction:[CCFollow actionWithTarget:hiddenPlayerSprite worldBoundary:CGRectMake(0, 0, MAX_LEVEL_WIDTH, MAX_LEVEL_HEIGH) ]];
    //9.enable touch
    this->setTouchEnabled(true);
    //10.enable move
    _isTouchToMove=false;
    //11.spawn bullet after schedule random sec
    this->schedule(schedule_selector(YHGameLayerMain::updatePlayerrShooting), 0.2f);

}

CCSprite * YHGameLayerMain::getPlayerSprite(){
    CCSpriteBatchNode *batchNode = (CCSpriteBatchNode *)this->getChildByTag(kTagBatchNode);
    return  (CCSprite *) batchNode->getChildByTag(kTagPalyer);
    
    
}

CCSprite * YHGameLayerMain::getAvailableEnemySprite()
{
    CCObject *obj =NULL;
    CCSprite * result =NULL;
    CCARRAY_FOREACH(_enemySprites, obj){
        result = (CCSprite*)obj;
        if (!result->isVisible()) {
            break;
        }
    }
    return result;

}

CCSprite * YHGameLayerMain::getAvailableBulletSprite()
{
    CCObject *obj =NULL;
    CCSprite * result =NULL;
    CCARRAY_FOREACH(_bulletSprites, obj){
        result = (CCSprite*)obj;
        if (!result->isVisible()) {
            break;
        }
    }
    return result;
    
}

void YHGameLayerMain::updateHUD(float dt){
    _lifeLabel->setString(CCString::createWithFormat("%2d",_totalLives)->getCString());
    _scoreLabel->setString(CCString::createWithFormat("%04d",_totalScore)->getCString());
}



void YHGameLayerMain::updatePlayerrShooting(float dt){
    CCSprite *playerSprite =(CCSprite*)this->getPlayerSprite();
    CCSprite *bulletSprite = this->getAvailableBulletSprite();
    CCPoint pos = playerSprite->getPosition();
    CCLOG("heroSprite x = %f , y = %f ",pos.x,pos.y);
    CCPoint bulletPos = CCPointMake(pos.x, pos.y+playerSprite->getContentSize().height/2+bulletSprite->getContentSize().height);
    bulletSprite->setPosition(bulletPos);
    bulletSprite->setVisible(true);
    CCSize winSize =CCDirector::sharedDirector()->getWinSize();
    CCActionInterval * bulletMove =CCMoveBy::create(1.0,ccp(0, winSize.height-bulletPos.y));
    bulletSprite->runAction(  CCSequence::create(
                                                   bulletMove,
                                                   CCCallFuncN::create(this, callfuncN_selector(YHGameLayerMain::bulletFinishedMoving)),
                                                   NULL));


}
void YHGameLayerMain::bulletFinishedMoving(CCNode* pSender){
    CCSprite *sp =(CCSprite *)pSender;
    sp->setVisible(false);
}

CCRect YHGameLayerMain::reckOfSprite(CCSprite *sprite){
    return CCRectMake(sprite->getPosition().x-sprite->getContentSize().width/2, sprite->getPosition().y-sprite->getContentSize().height/2, sprite->getContentSize().width, sprite->getContentSize().height);
    
}

void YHGameLayerMain::collisionDetection(float dt){
    CCObject *temp=NULL;
    CCARRAY_FOREACH(_enemySprites, temp){
        CCSprite * enemy =(CCSprite*)temp;
        if(enemy->isVisible() && _isEnemyColliable){
            CCRect enemyRect =this->reckOfSprite(enemy);
            //1.bullet & enemy collision detection
            CCObject *obj =NULL;
            CCSprite * result =NULL;
            CCARRAY_FOREACH(_bulletSprites, obj){
                result = (CCSprite*)obj;
                CCRect bulletRect = reckOfSprite(result);
                if (result->isVisible() &&  bulletRect.intersectsRect(enemyRect)) {
                    _isEnemyColliable=false;
                    CCScaleTo *ac1= CCScaleTo::create(1.0,1.2);
                    CCRotateBy *ac2= CCRotateBy::create(1.0,720);
                    CCFadeOut *ac3= CCFadeOut::create(1.0);
                    CCHide *ac4= CCHide::create();
                    CCAnimate *blowup =CCAnimate::create(_enemyBlowuoAnimation);
                    CCFiniteTimeAction *ac5 = CCSequence::create(ac3,ac4,CCCallFunc::create(this, callfunc_selector(YHGameLayerMain::resetEnemyPlane)),NULL);
                    CCFiniteTimeAction *action =(CCSpawn::create(ac1,ac2,ac5,blowup,NULL));
                    enemy->stopAllActions();
                    enemy->runAction(action);
                    //enemy.visible=NO;
                    result->setVisible(false);
                    _totalScore+=100;
                    if (_totalScore>=1000) {
                            _gameEndLabel->setString("游戏胜利！");
                            _gameEndLabel->setVisible(true);
                            CCScaleTo *scaleTo = CCScaleTo::create(1.0,1.2f);
                            _gameEndLabel->runAction(CCSequence::create(scaleTo,CCCallFunc::create(this, callfunc_selector(YHGameLayerMain::onRestartGame)),NULL));
                            
                    }
                    result->stopAllActions();
                    CCLOG("collision bullet");
                    break;
                }
            }
             
            //2.enemy & player collision detection
            CCSprite * playerSprite = (CCSprite *) this->getPlayerSprite();
            //CCSprite * playerSprite = (CCSprite *)[self getChildByTag:kTagPalyer];
            CCRect playerRect = this->reckOfSprite(playerSprite);
            if (playerSprite->isVisible()&&_isPlayerColliable&& enemyRect.intersectsRect(playerRect)) {
                enemy->setVisible(false);
                _totalLives-=1;
                if (_totalLives<=0) {
                    _gameEndLabel->setString("游戏失败！");
                    _gameEndLabel->setVisible(true);
                    CCScaleTo *scaleTo =CCScaleTo::create(1.0,1.2f);
                    _gameEndLabel->runAction(CCSequence::create(scaleTo,CCCallFunc::create(this, callfunc_selector(YHGameLayerMain::onRestartGame)),NULL));
                }
                
                CCBlink *blink = CCBlink::create(2.0,4);
                CCAnimate *blowup= CCAnimate::create(_playerBlowupAnimation);
                
                CCFiniteTimeAction *action = CCSequence::create(blowup,blink,CCCallFunc::create(this, callfunc_selector(YHGameLayerMain::resetPlayerPlane)),NULL);
                
                playerSprite->stopAllActions();
                playerSprite->runAction(action);
                //[enemy stopAllActions];
                CCLOG("collision player");
                break;
            }
        }
    }
    
}
void YHGameLayerMain::resetEnemyPlane(){
    _isEnemyColliable=true;
}

void YHGameLayerMain::resetPlayerPlane(){
    _isPlayerColliable =true;
    //重新运行飞机动画
    CCSprite * playerSprite = (CCSprite *) this->getPlayerSprite();
    playerSprite->stopAllActions();
    playerSprite->runAction(_playerFlyAction);
    playerSprite->setVisible(true);
}
void YHGameLayerMain::onRestartGame(){
    this->unscheduleUpdate();
    YHGameSceneManager::sharedGameSceneManager()->gotoScene((YHScene *)(CCTransitionFade::create(2.0f, YHGameMainScene::create())));
    
}


                                                    
void YHGameLayerMain::spawnEnemy(){
    
    //1.
    CCSize winSize =CCDirector::sharedDirector()->getWinSize();
    CCSprite *enemySprite = this->getAvailableEnemySprite();
    //2.
    float durationTime = arc4random()%4 +1;
    CCActionInterval * enemyMove =CCMoveBy::create(durationTime, ccp(0, -enemySprite->getPosition().y-enemySprite->getContentSize().height));
    enemySprite->setVisible(true);
    enemySprite->setPosition(ccp(arc4random()%(int)(winSize.width-enemySprite->getContentSize().width)+enemySprite->getContentSize().width/2, enemySprite->getPosition().y));
    CCLOG("enemySprite x = %f , y = %f ",enemySprite->getPosition().x,enemySprite->getPosition().y);
    
    enemySprite->runAction(  CCSequence::create(
                                                enemyMove,
                                                CCCallFuncN::create(this, callfuncN_selector(YHGameLayerMain::resetEnemy)),
                                                NULL));
    


    //3.
   // [self performSelector:_cmd withObject:nil afterDelay:arc4random()%3 +1];


}

void YHGameLayerMain::resetEnemy(CCNode* pSender){
    CCSize winSize =CCDirector::sharedDirector()->getWinSize();
    CCSprite *sp =(CCSprite *)pSender;
    sp->setVisible(false);
    sp->setPosition(ccp(0, winSize.height+sp->getContentSize().height+10));
    CCLOG("reset enemy plane!");

}

void YHGameLayerMain::ccTouchesBegan(CCSet *pTouches,CCEvent *pEvent){
    
    CCSetIterator it =pTouches->begin();
    CCTouch * touch =(CCTouch *)(*it);
    CCPoint m_tBeginPos = touch->locationInView();
    m_tBeginPos = CCDirector::sharedDirector()->convertToGL(m_tBeginPos);
    CCSprite *playerSprite=(CCSprite *)this->getPlayerSprite();
    CCPoint pt = this->convertToNodeSpace(m_tBeginPos);
    CCRect playerRect = playerSprite->boundingBox();
    if(playerRect.containsPoint(pt)){
        _isTouchToMove=true;
        int xdelta=pt.x-playerSprite->getPosition().x;
        int ydelta=pt.y-playerSprite->getPosition().y;
    }

}

void YHGameLayerMain::ccTouchesMoved(cocos2d::CCSet *pTouches,cocos2d::CCEvent *pEvent){
    CCSetIterator it =pTouches->begin();
    CCTouch * touch =(CCTouch *)(*it);
    CCPoint touchLocation = touch->locationInView();
    touchLocation=CCDirector::sharedDirector()->convertToGL(touchLocation);
    CCSprite *playerSprite=(CCSprite *)this->getPlayerSprite();
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    if(_isTouchToMove){
        playerSprite->setPosition(ccp(touchLocation.x-xdelta,touchLocation.y-ydelta));
    }

}

void YHGameLayerMain::ccTouchesEnded(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent){
    _isTouchToMove=false;

}

bool YHGameLayerMain::loadClouds()
{
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    m_spriteCloudsNear = CCSpriteBatchNode::create(s_cloud1);
    m_spriteCloudsNear->setPosition(ccp(0, 0));
    
    m_spriteCloudsFar = CCSpriteBatchNode::create(s_cloud2);
    m_spriteCloudsFar->setPosition(ccp(0, 0));
    
    
    this->addChild(m_spriteCloudsNear, kCloudNearZorder);
    this->addChild(m_spriteCloudsFar, kCloudFarZorder);
    
    this->schedule(schedule_selector(YHGameLayerMain::generateRandomClouds), 2);
    return true;
}

void YHGameLayerMain::generateRandomClouds(float t)
{
    //定义简单的云层加入，分两层，近层云离视线近，速度快，云层大。远层云离视线远，速度慢，云层小
    time(NULL);
    
    //加远层云
    int s = rand()%4;
    for (int t = 0; t < s; t ++) {
        CCSprite* cloudFar = CCSprite::createWithTexture(m_spriteCloudsFar->getTexture());
        cloudFar->ignoreAnchorPointForPosition(false);
        cloudFar->setAnchorPoint(ccp(0, 0));
        cloudFar->setScale(1.0f);
        int posX = rand()%220;
        int offset = t * 60;
        offset = (offset==0? 60 : offset);
        int offsetY = rand()%offset;
        int posY = 480 + offsetY;
        cloudFar->setPosition(ccp(posX, posY));
        m_spriteCloudsFar->addChild(cloudFar);
        
        float duration = (posY + 70 )/50 ;
        CCMoveBy* moveBy = CCMoveBy::create(duration, ccp(0,-70-posY));
        CCCallFuncN* callfuncN_cloud_near = CCCallFuncN::create(this, callfuncN_selector(YHGameLayerMain::removeCloud));
        CCFiniteTimeAction* sequence = CCSequence::create(moveBy, callfuncN_cloud_near, NULL);
        cloudFar->runAction(sequence);
    }
    
    //加近层云
    
    int i = rand()%3;
    for (int j = 0; j < i; j++) {
        CCSprite* cloudNear = CCSprite::createWithTexture(m_spriteCloudsNear->getTexture());
        cloudNear->ignoreAnchorPointForPosition(false);
        cloudNear->setAnchorPoint(ccp(0, 0));
        cloudNear->setScale(1.7f);
        int posX = rand()%220;
        int offset = j * 130;
        offset = (offset==0? 130 : offset);
        int offsetY = rand()%offset;
        int posY = 480 + offsetY;
        cloudNear->setPosition(ccp(posX, posY));
        m_spriteCloudsNear->addChild(cloudNear);
        
        float duration = (posY + 70 )/100 ;
        CCMoveBy* moveBy = CCMoveBy::create(duration, ccp(0,-120-posY));
        CCCallFuncN* callfuncN_cloud_near = CCCallFuncN::create(this, callfuncN_selector(YHGameLayerMain::removeCloud));
        CCFiniteTimeAction* sequence = CCSequence::create(moveBy, callfuncN_cloud_near, NULL);
        cloudNear->runAction(sequence);
    }
    
    
}

void YHGameLayerMain::removeCloud(CCNode* nodeCloud)
{
    CCSprite* sprite = (CCSprite*)nodeCloud;
    if (sprite->getParent()) {
        sprite->removeFromParentAndCleanup(true);
    }
}